package com.css.ids.server.service.dao;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collection;
import java.util.Date;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.hibernate.HibernateException;

import com.css.apps.base.common.BaseEnvironment;
import com.css.apps.base.common.Constants;
import com.css.apps.base.func.model.SFunc;
import com.css.apps.base.func.model.SFuncAction;
import com.css.apps.base.org.model.SOrg;
import com.css.apps.base.org.model.SUserOrg;
import com.css.apps.base.security.model.SecurityParam;
import com.css.apps.base.security.service.SecurityService;
import com.css.apps.base.sysjob.model.SysJob;
import com.css.apps.base.user.model.SUser;
import com.css.apps.base.user.model.SUserRole;
import com.css.common.exception.base.CssBaseException;
import com.css.core.configuration.Environment;
import com.css.core.model.tree.Tree;
import com.css.core.model.tree.TreeCache;
import com.css.core.model.tree.TreeNode;
import com.css.db.query.QueryCache;
import com.css.db.query.TransactionCache;
import com.css.util.ListUtil;
import com.css.util.Md5Util;
import com.css.util.StringHelper;
import com.css.util.UuidUtil;

public class IdsUserDao {

	@SuppressWarnings("unchecked")
	public static List<SUser> listUsers(Collection<String> userIds) {
		List<SUser> users = QueryCache.idToObj(SUser.class, new ArrayList<>(userIds));
		return validateUser(users);
	}
	
	public static void loadUserAuth(SUser user, String sysId) {
        if (user != null) {
            List<SFunc> funcs = IdsFuncDao.getFuncByUserId(user.getUuid(), sysId);
            List<SFuncAction> actions = IdsFuncDao.getFuncActionByUserId(user.getUuid(), sysId);
            if (funcs != null && funcs.size() > 0) {
                Set<String> functions = new HashSet<String>();
                for (SFunc func : funcs) {
                    functions.add(func.getFuncCode());
                }
                user.setFunctions(functions);
            }
            if (actions != null && actions.size() > 0) {
                Set<String> funcations = new HashSet<String>();
                for (SFuncAction action : actions) {
                    funcations.add(action.getActionCode());
                }
                user.setFuncActions(funcations);
            }
            user.setFuncs(funcs);
            user.setActions(actions);
        }
    }
	
	@SuppressWarnings("unchecked")
    public static SUser getUserByUserId(String userId) {
        SUser user = QueryCache.get(SUser.class, userId);
        user.setSyss(user.getSysList().getList());
        user.setRoles(user.getRoleList().getList());
        user.setPosts(user.getPostList().getList());
        user.setOrgs(user.getOrgList().getList());
        return user;
    }
	
	public static SUser getUserByLoginName(String loginName) {
        StringBuffer sb = new StringBuffer(" select uuid from SUser where loginName=:loginName ");
        QueryCache qc = new QueryCache(sb.toString()).setParameter("loginName", loginName);
        String userId = (String) qc.uniqueResult();
        if (userId == null) return null;
        return validateUser(QueryCache.get(SUser.class, userId));
    }
	
	public static SUser getUserByLoginName(String loginName, String loginPwd) {
        StringBuffer sb = new StringBuffer(" select uuid from SUser where loginName=:loginName and password=:loginPwd  ");
        QueryCache qc = new QueryCache(sb.toString()).setParameter("loginName", loginName).setParameter("loginPwd", loginPwd);
        String userId = (String) qc.uniqueResult();
        if (userId == null) return null;
        return validateUser(QueryCache.get(SUser.class, userId));
    }
	
	/**
     * 根据用户名称模糊查询用户基本信息列表
     */
    @SuppressWarnings("unchecked")
    public static List<SUser> listUsersByName(String userName) {
        StringBuffer sb = new StringBuffer("select distinct a.uuid from SUser a where a.realName like :userName ");
        QueryCache qc = new QueryCache(sb.toString()).setParameter("userName", "%" + userName + "%");
        return validateUser(QueryCache.idToObj(SUser.class, qc.list()));
    }
	
    /**
     * 根据机构ID获取用户基本信息列表
     * @param withChildren 
     */
    @SuppressWarnings("unchecked")
    public static List<SUser> listUsersByDept(String deptId, boolean withChildren) {
    	StringBuffer sb = new StringBuffer("from SUser");
    	List<SUser> susers = null;
    	QueryCache qc = null;
    	if (withChildren) {
    		sb.append(" where uuid in (select distinct userId from SUserOrg where deptId in (:orgIds)) order by orderNum");
    		List<String> orgIds = new ArrayList<>();
    		Tree tree = new TreeCache(SOrg.class);
    		TreeNode node = tree.getTreeNode(deptId);
    		List<TreeNode> childrenNode = node.getAllChildren();
    		orgIds.add(deptId);
    		for (TreeNode childNode : childrenNode) {
				orgIds.add(childNode.getNodeId());
			}
    		qc = new QueryCache(sb.toString()).setParameter("orgIds", orgIds);
    	} else {
    		sb.append(" where uuid in (select distinct userId from SUserOrg where deptId = :orgId) order by orderNum");
    		qc = new QueryCache(sb.toString()).setParameter("orgId", deptId);
    	}
    	susers = qc.list();
        return validateUser(susers);
    }
    
    /**
     * 根据机构ID和岗位ID获取当前机构下用户基本信息列表
     */
    @SuppressWarnings("unchecked")
    public static List<SUser> listUsersByOrgPost(String orgId, String postId) {
        StringBuffer sb = new StringBuffer(" select distinct a.userId from SUserOrg a where a.orgId = :orgId and a.userId in (");
        sb.append("select b.userId from SUserPost b where b.postId = :postId)");
    	/*StringBuffer sb = new StringBuffer("select a.userId from SUserPost a where a.orgId = :orgId and a.postId = :postId");*/
    	
        QueryCache qc = new QueryCache(sb.toString()).setParameter("orgId", orgId).setParameter("postId", postId);
        List<SUser> susers = QueryCache.idToObj(SUser.class, qc.list());
        return validateUser(susers);
    }
    
    /**
     * 查出本部门下的所有子部门 orgList
     * 查询本部门及子部门的在设定岗位下的人员
     * userList:select uuid from SUser where openFlag =1 and deleteFlag =2 
     * 				and uuid in (select userId from SUserPost where postId = ?)
     * select userId from SUserOrg where orgId in (orgList) and userId in (userList);
     *
     * @param secondOrgId
     * @param postId
     * @return
     * @author liuhy
     * 2017年3月29日 下午4:32:45
     */
    @SuppressWarnings("unchecked")
    public static List<SUser> listUsersBySecondLevelPost(String secondOrgId, String postId) {
        // 查找厅级部门下的子部门
        List<String> orgIds = new ArrayList<>();
        Tree orgTree = new TreeCache(SOrg.class);
        TreeNode secondeOrg = orgTree.getTreeNode(secondOrgId);
        orgIds.add(secondOrgId);
        List<TreeNode> children = secondeOrg.getAllChildren();
        for (TreeNode node : children) {
            orgIds.add(node.getNodeId());
        }
        List<String> userIds = new ArrayList<>();
        List<SUser> users = queryUsersByPost(postId);
        if (!ListUtil.isLstEmpty(users)) {
            for (SUser user : users) {
                userIds.add(user.getUserId());
            }
        }
        StringBuffer sb = new StringBuffer();
        sb.append("select distinct userId from SUserOrg where orgId in (:orgList) and userId in (:userList)");
        QueryCache qc = new QueryCache(sb.toString()).setParameter("orgList", orgIds).setParameter("userList", userIds);
        List<SUser> susers = QueryCache.idToObj(SUser.class, qc.list());
        return validateUser(susers);
    }
    
    /**
     * 根据岗位ID获取用户基本信息列表
     */
    @SuppressWarnings("unchecked")
    public static List<SUser> queryUsersByPost(String postId) {
        StringBuffer sb = new StringBuffer("select distinct userId from SUserPost where postId = :postId");
        QueryCache qc = new QueryCache(sb.toString()).setParameter("postId", postId);
        List<SUser> susers = QueryCache.idToObj(SUser.class, qc.list());
        return validateUser(susers);
    }
    
    /**
     * 同步用户基本信息
     * @param time  time为null为全量，time有值时为增量
     */
    @SuppressWarnings("unchecked")
    public static List<SUser> syncUsers(Date time, String sysId) {
        StringBuffer sb = new StringBuffer(" select uuid from SUser ");
        if (null != time) {
            sb.append(" where editDate >= :editDate and (userType='1' or userType='5') ");
        }
        QueryCache qc = new QueryCache(sb.toString());
        if (null != time) {
            qc.setParameter("editDate", time);
        }
        List<String> ids = qc.list();
        if (ids == null) {
            return null;
        }
        return QueryCache.idToObj(SUser.class, ids);
    }
    
    // FIXME
    @SuppressWarnings("unchecked")
	public static List<SUser> queryUsersByParentOrgPost(String orgId, String postId) {
        StringBuffer sb = new StringBuffer("select d.uuid from S_User d where orgId in (select distinct a.uuid from S_Org a, S_Org_Post b ");
        sb.append("where (a.uuid = :orgId or a.parentId = :orgId) and a.uuid = b.orgId ");
        sb.append("and b.postId = :postId)");
        QueryCache qc = new QueryCache(sb.toString(), true).setParameter("orgId", orgId).setParameter("postId", postId);
        return qc.idToObject(SUser.class, qc.list());
    }
    
    @SuppressWarnings("unchecked")
    public static List<SUser> queryUsersByRole(String roleId) {
        List<String> userIds = new QueryCache("select userId from SUserRole where roleId = :roleId").setParameter("roleId", roleId).list();
        return QueryCache.idToObj(SUser.class, userIds);
    }
    
    @SuppressWarnings("unchecked")
	public static List<SUser> queryUsersBySysAndOrg(List<String> sysList, List<String> orgList) {
		boolean sysListIsNull = ListUtil.isLstEmpty(sysList), orgListIsNull = ListUtil.isLstEmpty(orgList);
		StringBuffer sb = new StringBuffer("select distinct userId from SUserRole where 1 = 1 ");
		sb.append(sysListIsNull ? "" : "and sysId in (:sysIds) ")
			.append(orgListIsNull ? "" : "and userId in (select userId from SUserOrg where orgId in (:orgIds))");
		QueryCache qc = new QueryCache(sb.toString());
		if(!sysListIsNull) {
			qc.setParameter("sysIds", sysList);
		}
		if(!orgListIsNull) {
			qc.setParameter("orgIds", orgList);
		}
		List<String> userIds = qc.list();
		return validateUser(QueryCache.idToObj(SUser.class, userIds));
	}
    
	public static List<SUser> getUserByFilter(Map<String, Object> conditions) {
    	List<SUser> users = getUserByFilter(null, conditions);
    	return validateUser(users);
    }

    @SuppressWarnings("unchecked")
    public static List<SUser> getUserByFilter(List<String> orgIdList, Map<String, Object> conditions) {
        Set<String> keys = conditions.keySet();
        StringBuffer sb = new StringBuffer("from SUser where 1 = 1 ");
        for (String key : keys) {
            if ("realName".equalsIgnoreCase(key) || "loginName".equalsIgnoreCase(key)) {
                sb.append(" and ").append(key).append(" like :").append(key);
            } else {
            	sb.append(" and ").append(key).append(" = :").append(key);
            }
        }
        QueryCache qc = new QueryCache(sb.toString());
        for (String key : keys) {
            if (StringHelper.isNotEmpty(key)) {
                if ("realName".equalsIgnoreCase(key) || "loginName".equalsIgnoreCase(key)) {
                    qc.setParameter(key, "%" + conditions.get(key) + "%");
                } else {
                	qc.setParameter(key, conditions.get(key));
                }
            }
        }
        List<SUser> userList = qc.list();
        return userList.size() == 0 ? null : userList;
    }
	
    @SuppressWarnings("unchecked")
	public static List<SUser> listAllUser() {
    	List<SUser> users = new QueryCache("from SUser").list();
    	return validateUser(users);
    }
    
    @SuppressWarnings("unchecked")
	public static List<SUser> listAllUser(int orgLevel) {
    	StringBuffer sb = new StringBuffer("from SUser where delFlag = '2' and openFlag = '1' and userType = '1' ");
    	sb.append("and uuid in (")
			.append("select userId from SUserOrg where orgId in (select uuid from SOrg where orgType = '1' and orgLevel = :orgLevel)")
			.append(")");
    	QueryCache qc = new QueryCache(sb.toString()).setParameter("orgLevel", orgLevel);
    	return qc.list();
    }
    
    /**
     * 获取单位中所有用户
     */
    @SuppressWarnings("unchecked")
    public static List<SUser> listCorporationAllUser(String corpId) {
    	StringBuffer sb = new StringBuffer("from SUser where delFlag = '2' and openFlag = '1' and userType = '1' ");
		sb.append("and uuid in (select userId from SUserOrg where orgId = :orgId)");
    	QueryCache qc = new QueryCache(sb.toString()).setParameter("orgId", corpId);
        return qc.list();
    }
    
	public static boolean updUsers(Map<String, Map<String, Object>> conditions) {
        TransactionCache tx = new TransactionCache();
        List<SUser> users = new ArrayList<>();

        Iterator<String> userIds = conditions.keySet().iterator();
        while (userIds.hasNext()) {
            String userId = userIds.next();
            SUser user = getUserByUserId(userId);
            Map<String, Object> upds = conditions.get(userId);
            Iterator<String> keys = upds.keySet().iterator();
            while (keys.hasNext()) {
                String key = keys.next();
                if ("email".equals(key)) {
                	user.setEmail(String.valueOf(upds.get(key)));
                } else if ("mobile".equals(key)) {
                	user.setMobile(String.valueOf(upds.get(key)));
                } else if ("password".equals(key)) {
                	try {
						user.setPassword(Md5Util.getMD5(Md5Util.getMD5(String.valueOf(upds.get(key)))));
					} catch (Exception e) {
						e.printStackTrace();
					}
                }
            }
            users.add(user);
        }
        try {
            tx.update(users);
        } catch (HibernateException e) {
            e.printStackTrace();
            return false;
        }
        tx.commit();
        return true;
    }
	
	@SuppressWarnings("unchecked")
	private static <T> T validateUser(T t) {
    	if(t instanceof List) {
    		List<SUser> users = (List<SUser>) t;
    		List<SUser> userList = null;
    		if(ListUtil.isLstNotEmpty(users)) {
    			userList = new ArrayList<>();
    			for (SUser user : users) {
    	            if (Constants.NO.equals(user.getDelFlag()) && Constants.YES.equals(user.getOpenFlag()) && "3".equals(user.getActiveStatus())
    	                    && (BaseEnvironment.USERTYPE_NORMAL.equals(user.getUserType()) 
    	                    		|| BaseEnvironment.USERTYPE_BIZADMIN.equals(user.getUserType())
    	                    		|| "6".equals(user.getUserType()))) {
    	                userList.add(user);
    	            }
    	        }
    		}
    		return (T) userList;
    	}
    	if(t instanceof SUser) {
    		SUser user = (SUser) t;
    		/**
    		 * userType为1 ==> 普通用户
    		 * 5 ==> 业务系统管理员用户
    		 * 6 ==> 其他用户(总部"人力资源部其他人员"用户)
    		 */
    		if (Constants.NO.equals(user.getDelFlag()) && Constants.YES.equals(user.getOpenFlag()) && "3".equals(user.getActiveStatus())
                    && (BaseEnvironment.USERTYPE_NORMAL.equals(user.getUserType()) || BaseEnvironment.USERTYPE_BIZADMIN.equals(user.getUserType())
                    		|| "6".equals(user.getUserType()))) {
    			return t;
    		}
    	}
    	return null;
    }

	@SuppressWarnings("unchecked")
	public static void addOrUpdUser(SUser user, List<SysJob> sysjobList) {
		List<Object> addList = new ArrayList<>(), delList = new ArrayList<>();
		String userId = user.getUuid();
		SUser sUser = QueryCache.get(SUser.class, userId);
		if (sUser == null) {
			user.setUserType(Environment.NORMALUSER + "");
			String password = SecurityService.getParamValue(SecurityParam.INIT_PASSWORD);
			if (StringHelper.isEmpty(password)) {
				user.setPassword(Md5Util.MD5Encode(Md5Util.MD5Encode("password01!")));
			} else {
				user.setPassword(Md5Util.MD5Encode(Md5Util.MD5Encode(password)));
			}
			Date now = Calendar.getInstance().getTime();
			user.setIssueDate(now);
			user.setIssueId("syncFromHR");
			user.setIssueName("syncFromHR");
			user.setEditDate(now);
			user.setTotalLoginCount(0);
			user.setFailedLoginCount(0);
			user.setOpenFlag(Environment.DELETE_STATE);
			user.setDelFlag(Environment.UN_DELETE_STATE);
			user.setActiveStatus("3");
			addList.add(user);
		} else {
			delList.addAll(new QueryCache("from SUserRole where userId = :userId").setParameter("userId", userId).list());
			delList.addAll(new QueryCache("from SUserOrg where userId = :userId").setParameter("userId", userId).list());
		}
		addList.addAll(initUserOrgRole(userId, sysjobList, addList));
		try {
			TransactionCache tx = new TransactionCache();
			tx.delete(delList);
			tx.save(addList);
			if (sUser != null) {
				tx.update(user);
			}
			tx.commit();
		} catch (HibernateException e) {
			e.printStackTrace();
			throw new CssBaseException("systemMsg.dbFaild");
		}
	}
	
	private static List<Object> initUserOrgRole(String userId, List<SysJob> sysjobList, List<Object> res) {
		if (sysjobList != null) {
			for (SysJob sysjob : sysjobList) {
				SUserOrg userorg = new SUserOrg();
				userorg.setOrgId(sysjob.getOrgId());
				userorg.setUserId(userId);
				userorg.setUuid(UuidUtil.getUuid());
				res.add(userorg);
				SUserRole userrole = new SUserRole();
				userrole.setSysId(sysjob.getSysId());
				userrole.setRoleId(sysjob.getRoleId());
				userrole.setUserId(userId);
				userrole.setUuid(UuidUtil.getUuid());
				res.add(userrole);
			}
		}
		return res;
	}

	@SuppressWarnings("unchecked")
	public static List<SUser> queryUsersByPost(String deptId, String postName) {
		StringBuilder hql = new StringBuilder("select userId from SUserPost");
		hql.append(" where orgId = orgId and postId = (")
			.append("select uuid from SPost where name = :postName")
			.append(")");
		List<String> userIds = new QueryCache(hql.toString()).list();
		return validateUser(QueryCache.idToObj(SUser.class, userIds));
	}
	
}
